import ctypes
from ctypes import Structure, POINTER, c_int, c_void_p, c_char, pointer
from ctypes.wintypes import LPCSTR, WORD, DWORD, LONG, LPVOID, HWND, UINT, BYTE

OF_READ = 0x00000000
OF_WRITE = 0x00000001
OF_CREATE = 0x00001000
OF_SHARE_DENY_WRITE = 0x00000020
WAVE_FORMAT_SPEEX = 0xa109
AVIIF_KEYFRAME = 0x00000010L

def fourcc(s):
    return sum(256**i*ord(c) for i, c in enumerate(s))

class AVIFILEINFO(Structure):
    _fields_ = [
        ("dwMaxBytesPerSec", DWORD),
        ("dwFlags", DWORD),
        ("dwCaps", DWORD),
        ("dwStreams", DWORD),
        ("dwSuggestedBufferSize", DWORD),
        ("dwWidth", DWORD),
        ("dwHeight", DWORD),
        ("dwScale", DWORD),
        ("dwRate", DWORD),
        ("dwLength", DWORD),
        ("dwEditCount", DWORD),
        ("szName", c_char*64)
    ]

class RECT(Structure):        # for UI?
    _fields_ = zip(["left","top","right","bottom"], [LONG]*4)

class AVICOMPRESSOPTIONS(Structure):
    _fields_ = [
        ("fccType", DWORD),
        ("fccHandler", DWORD),
        ("dwKeyFrameEvery", DWORD),
        ("dwQuality", DWORD),
        ("dwBytesPerSecond", DWORD),
        ("dwFlags", DWORD),
        ("lpFormat", LPVOID),
        ("cbFormat", DWORD),
        ("lpParams", LPVOID),
        ("cbParams", DWORD),
        ("dwInterLeaveEvery", DWORD)
   ]

class AVISTREAMINFOA(Structure):
    _fields_ = [
        ("fccType", DWORD),
        ("fccHandler", DWORD),
        ("dwFlags", DWORD),
        ("dwCaps", DWORD),
        ("wPriority", WORD),
        ("wLanguage", WORD),
        ("dwScale", DWORD),
        ("dwRate", DWORD),
        ("dwStart", DWORD),
        ("dwLength", DWORD),
        ("dwInitialFrames", DWORD),
        ("dwSuggestedBufferSize", DWORD),
        ("dwQuality", DWORD),
        ("dwSampleSize", DWORD),
        ("rcFrame", RECT),
        ("dwEditCount", DWORD),
        ("dwFormatChangeCount", DWORD),
        ("szName", c_char*64)
        ]

class BITMAPINFOHEADERA(Structure):
    _fields_ = [
        ("biSize", DWORD),
        ("biWidth", LONG),
        ("biHeight", LONG),
        ("biPlanes", WORD),
        ("biBitCount", WORD),
        ("biCompression", DWORD),
        ("biSizeImage", DWORD),
        ("biXPelsPerMeter", LONG),
        ("biYPelsPerMeter", LONG),
        ("biClrUsed", DWORD),
        ("biClrImportant", DWORD),
    ]

class WAVEFORMATEX(Structure):
    _fields_ = [
        ("wFormatTag", WORD),
        ("nChannels", WORD),
        ("nSamplesPerSec", DWORD),
        ("nAvgBytesPerSec", DWORD),
        ("nBlockAlign", WORD),
        ("wBitsPerSample",WORD),
        ("cbSize",WORD),
        ("nVersion", WORD),
        ("nFramesPerBlock", WORD),
        ("nQuality", WORD),
        ("nMode", WORD),
        ("nVbrQuality", WORD),
        ("nComplexity", WORD),
        ("nFlags", WORD),
    ]

class RGBQUAD(Structure):
    _fields_ = [
        ("rgbBlue", BYTE),
        ("rgbGreen", BYTE),
        ("rgbRed", BYTE),
        ("rgbReserved", BYTE),
                ]

avi = ctypes.windll.LoadLibrary("avifil32.dll")
#hdecoder = ctypes.windll.LoadLibrary("ffmpeg.dll")

avi.AVIFileOpen.argtypes = [POINTER(c_int), LPCSTR, c_int, c_int]
avi.AVIFileOpen.restype = c_int

avi.AVIFileCreateStream.argtypes = [c_int, POINTER(c_void_p), POINTER(AVISTREAMINFOA)]
avi.AVIFileCreateStream.restype = c_int

avi.AVISaveOptions.argtypes = [HWND, UINT, c_int, POINTER(c_void_p), c_void_p]
avi.AVISaveOptions.restype = c_int

avi.AVIFileRelease.argtypes = [c_int]
avi.AVIFileRelease.restype = c_int

avi.AVIStreamRelease.argtypes = [c_void_p]
avi.AVIStreamRelease.restype = c_int

avi.AVIStreamSetFormat.argtypes = [c_void_p, c_int, c_void_p, c_int]
avi.AVIStreamSetFormat.restype = c_int

avi.AVIStreamWrite.argtypes = [c_void_p, c_int, c_int, c_void_p, c_int, c_int, c_int, c_int]
avi.AVIStreamWrite.restype = c_int

vinfo = AVISTREAMINFOA()
vinfo.fccType = fourcc('vids')
vinfo.dwRate = 10
vinfo.dwScale = 1
vinfo.fccHandler = fourcc('J264')
vinfo.dwSuggestedBufferSize = 320*240*3
vinfo.rcFrame.left = 0
vinfo.rcFrame.top = 0
vinfo.rcFrame.right = 320
vinfo.rcFrame.bottom = 240

cinfo = AVISTREAMINFOA()
cinfo.fccType = fourcc('vids')
cinfo.dwRate = 10
cinfo.dwScale = 1
cinfo.fccHandler = fourcc('SJSC')
cinfo.dwSuggestedBufferSize = 800*600*4
cinfo.rcFrame.left = 0
cinfo.rcFrame.top = 0
cinfo.rcFrame.right = 800
cinfo.rcFrame.bottom = 600

ainfo = AVISTREAMINFOA()
ainfo.fccType = fourcc('auds')
ainfo.fccHandler = 0xa109
ainfo.dwScale = 42
ainfo.dwRate = 2100
ainfo.dwSuggestedBufferSize = 0
ainfo.dwSampleSize = 42
ainfo.rcFrame.left = 0
ainfo.rcFrame.top = 0
ainfo.rcFrame.right = 0
ainfo.rcFrame.bottom = 0

binfo = BITMAPINFOHEADERA()
binfo.biWidth = 320
binfo.biHeight = 240
binfo.biSize = ctypes.sizeof(BITMAPINFOHEADERA)
binfo.biPlanes = 1
binfo.biBitCount = 24
binfo.biCompression = fourcc('J264')
binfo.biSizeImage = 320*240*3

sinfo = BITMAPINFOHEADERA()
sinfo.biSize = ctypes.sizeof(BITMAPINFOHEADERA)
sinfo.biWidth = 800
sinfo.biHeight = 600
sinfo.biPlanes = 1
sinfo.biBitCount = 16
sinfo.biCompression = fourcc('SJSC')
sinfo.biSizeImage = 800*600*4

winfo = WAVEFORMATEX()
winfo.wFormatTag = 0xa109
winfo.nAvgBytesPerSec = 2100
winfo.nBlockAlign = 42
winfo.nChannels = 1
winfo.nSamplesPerSec = 16000
winfo.wBitsPerSample = 16
winfo.cbSize = 14
winfo.nVersion = 0x0100
winfo.nFramesPerBlock = 1
winfo.nQuality = 5
winfo.nMode = 0
winfo.nVbrQuality = 500
winfo.nComplexity = 3
winfo.nFlags = 0